#include "MediaConnectionsHandler.h"
#include "MediaEventSetupConnection.h"
#include "MediaEventReleaseConnection.h"
#include "Trace.h"

namespace tsc
{
namespace mgw
{

using namespace tsc::common;

MediaConnectionsHandler* MediaConnectionsHandler::_instance = 0;

/*******************************************************************************
 *
 * Constructor
 *
 ******************************************************************************/
MediaConnectionsHandler::MediaConnectionsHandler(
		GeneratorEnvironment& ge):
	_ge(ge)
{

} // MediaConnectionsHandler::MediaConnectionsHandler

/*******************************************************************************
 *
 * Destructor
 *
 ******************************************************************************/
MediaConnectionsHandler::~MediaConnectionsHandler()
{

}

void MediaConnectionsHandler::init(GeneratorEnvironment& ge)
{
	if(!_instance)
	{
		_instance = new MediaConnectionsHandler(ge);
	}
}

//===================================================================
MediaConnectionsHandler& MediaConnectionsHandler::instance()
{
    if(!_instance)
    {
    	TRACE_ERROR("Generator not initialized");
    }
    return *_instance;
}
//===================================================================
bool
MediaConnectionsHandler::findConnection(
    uint32_t connectionId,
    MediaGenerator*& gen)
{
    std::map<uint32_t, MediaGenerator*>::iterator it;
    it = mConnMap.find(connectionId);
    if(it != mConnMap.end())
    {
        TRACE(8, STR("MediaConnection with ID=0x%x found", connectionId));
        gen = it->second;
        return true;
    }
    TRACE(8, STR("MediaConnection with ID=0x%x NOT found", connectionId));
    return false;
}

//===================================================================
bool
MediaConnectionsHandler::setupConnection(
    MediaGenerator*& mediaGen,
    uint32_t connectionId,
    ProtocolsCommon::IpAddress* clientIp,
    uint32_t clientMediaPort,
    uint32_t mediaItemId)
{
    TRACE(3, STR("Setting up MediaConnection, connId=0x%x, clientIp=%s, "
            "clientMediaPort=%u, mediaItemId=%u",
            connectionId, clientIp->DebugString().c_str(),
            clientMediaPort, mediaItemId));

    // first check if connection exists just to be sure
    if(findConnection(connectionId, mediaGen))
    {
        TRACE(1, STR("MediaConnection with ID=0x%x already exists", connectionId));
        mediaGen = 0;
        return false;
    }

    mediaGen = new MediaGenerator(_ge);
    common::EventData* event = new MediaEventSetupConnection(connectionId,
                                                             clientIp,
                                                             clientMediaPort,
                                                             mediaItemId);

    mediaGen->injectEvent(event);

    // TODO - create socket for specified params, ClientIp, clientMediaPort

    // TODO after socket creation we need to set port on which the
    // server socket is listening - that is UserClient will try to
    // open it's media socket to this port
    // XXX this mediaServerPort is known from the beginning
    mediaGen->setServerMediaPort(66);

    // if everything went fine add generator to map
    mConnMap.insert(std::pair<uint32_t, MediaGenerator*>(connectionId, mediaGen));

    return true;
}

//===================================================================
bool
MediaConnectionsHandler::releaseConnection(
    uint32_t connectionId)
{
    MediaGenerator* mediaGen = 0;
    if(findConnection(connectionId, mediaGen))
    {
        TRACE(3, STR("Releasing media connection, ID=0x%x", connectionId));
        common::EventData* event =
                new MediaEventReleaseConnection(connectionId);
        mediaGen->injectEvent(event);

        mConnMap.erase(connectionId);

        if(event)
        {
            delete event;
        }
        delete mediaGen;
    }
    return false;
}

} // namespace mgw
} // namespace tsc
